---
title: Tooltip
description: Using the tooltip machine in your project.
package: "@zag-js/tooltip"
---

A tooltip is a brief, informative message that appears when a user interacts
with an element. Tooltips are usually initiated when a button is focused or
hovered.

<Resources pkg="@zag-js/tooltip" />

<Showcase id="Tooltip" />

**Features**

- Show tooltip on hover and focus
- Hide tooltip on esc or pointer down
- Only one tooltip shows at a time
- Labeling support for screen readers via `aria-describedby`
- Custom show and hide delay support
- Matches native tooltip behavior with delay on hover of first tooltip and no
  delay on subsequent tooltips

## Installation

To use the tooltip machine in your project, run the following command in your
command line:

<CodeSnippet id="tooltip/installation.mdx" />

## Anatomy

To set up the tooltip correctly, you'll need to understand its anatomy and how
we name its parts.

> Each part includes a `data-part` attribute to help identify them in the DOM.

<Anatomy id="tooltip" />

## Usage

First, import the tooltip package into your project

```jsx
import * as tooltip from "@zag-js/tooltip"
```

The tooltip package exports two key functions:

- `machine` — The state machine logic for the tooltip widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

To get the tooltip working correct, you'll need to:

- Setup the tooltip portal, this is a shared container for all tooltips
- Add the `triggerProps`, and `tooltipProps` to the elements

> You'll also need to provide a unique `id` to the `useMachine` hook. This is
> used to ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
tooltip machine in your project 🔥

<CodeSnippet id="tooltip/usage.mdx" />

### Customizing the timings

By default, the tooltip is designed to open after `1000ms` and close after
`500ms`. You can customize this by passing the `openDelay` and `closeDelay`
context properties.

```jsx {2-3}
const service = useMachine(tooltip.machine, {
  openDelay: 500,
  closeDelay: 200,
})
```

### Changing the placement

The tooltip uses [floating-ui](https://floating-ui.com/) for dynamic
positioning. You can change the placement of the tooltip by passing the
`positioning.placement` context property to the machine.

```jsx {2-4}
const service = useMachine(tooltip.machine, {
  positioning: {
    placement: "bottom-start",
  },
})
```

You can configure other position-related properties in the `positioning` object.
Here's what the positioning API looks like:

```ts
export type PositioningOptions = {
  /**
   * The strategy to use for positioning
   */
  strategy?: "absolute" | "fixed"
  /**
   * The initial placement of the floating element
   */
  placement?: Placement
  /**
   * The offset of the floating element
   */
  offset?: { mainAxis?: number; crossAxis?: number }
  /**
   * The main axis offset or gap between the reference and floating elements
   */
  gutter?: number
  /**
   * Whether to flip the placement
   */
  flip?: boolean
  /**
   * Whether to make the floating element same width as the reference element
   */
  sameWidth?: boolean
  /**
   * The overflow boundary of the reference element
   */
  boundary?: Boundary
  /**
   * Options to activate auto-update listeners
   */
  listeners?: boolean | AutoUpdateOptions
}
```

### Adding an arrow

To render an arrow within the tooltip, use the `api.getArrowProps()` and
`api.getArrowTipProps()`.

```jsx {6-8}
//...
const api = popover.connect(service, normalizeProps)
//...
return (
  <div {...api.getPositionerProps()}>
    <div {...api.getArrowProps()}>
      <div {...api.getArrowTipProps()} />
    </div>
    <div {...api.getContentProps()}>{/* ... */}</div>
  </div>
)
//...
```

### Pointerdown behavior

By default, the tooltip will close when the pointer is down on its trigger. To
prevent this behavior, pass the `closeOnPointerDown` context property and set it
to `false`.

```jsx {2}
const service = useMachine(tooltip.machine, {
  closeOnPointerDown: false,
})
```

### Closing on Esc

The tooltip is designed to close when the escape key is pressed. To prevent
this, pass the `closeOnEscape` context property and set it to `false`.

```jsx {2}
const service = useMachine(tooltip.machine, {
  closeOnEsc: false,
})
```

### Making the tooltip interactive

Set the `interactive` context property to `true` to make them interactive.

When a tooltip is interactive, it'll remain open even the pointer leaves the
trigger and move into the tooltip's content.

```jsx {2}
const service = useMachine(tooltip.machine, {
  interactive: true,
})
```

### Listening for open state changes

When the tooltip is opened or closed, the `onOpenChange` callback is invoked.

```jsx {2-7}
const service = useMachine(tooltip.machine, {
  onOpenChange(details) {
    // details => { open: boolean }
    console.log(details.open)
  },
})
```

## Styling guide

Earlier, we mentioned that each tooltip part has a `data-part` attribute added
to them to select and style them in the DOM.

```css
[data-part="trigger"] {
  /* styles for the content */
}

[data-part="content"] {
  /* styles for the content */
}
```

### Open and close states

When the tooltip is open, the `data-state` attribute is added to the trigger

```css
[data-part="trigger"][data-state="open|closed"] {
  /* styles for the trigger's expanded state */
}

[data-part="content"][data-state="open|closed"] {
  /* styles for the trigger's expanded state */
}
```

### Styling the arrow

When using arrows within the menu, you can style it using css variables.

```css
[data-part="arrow"] {
  --arrow-size: 20px;
  --arrow-background: red;
}
```

## Methods and Properties

### Machine Context

The tooltip machine exposes the following context properties:

<ContextTable name="tooltip" />

### Machine API

The tooltip `api` exposes the following methods:

<ApiTable name="tooltip" />

### Data Attributes

<DataAttrTable name="tooltip" />

### CSS Variables

<CssVarTable name="tooltip" />

## Accessibility

### Keyboard Interactions

<KeyboardTable name="tooltip" />
